// graph http client -- needs work!
package http

import (
	"code.google.com/p/cloud9lib/restc"
	"net/url"
	"code.google.com/p/feedgraph/graph"
	"code.google.com/p/feedgraph/config"
	"strconv"
)

type Edge struct {
	Source, Sink, Relation string
}

type Proxy struct {
	base string
	g string
}

type NodeProxy struct {
	graph Proxy
	node string
}

type EdgeHandler func(graph.Edge)

type params struct {
	since string
	block string
	min string
	max string
}

func Graph(name string) Proxy {

	return Proxy{config.Local.HTTPConfig.APIBaseURL, url.QueryEscape(name)}
}

func (p Proxy) Link(src, rel string, obj interface{}) error {

	urlstr := restc.Url(p.base, p.g, src, rel)

	err := restc.Put(urlstr, nil, obj)

	return err
}

func (p Proxy) SetNode(node string, obj interface{}) error {

	urlstr := restc.Url(p.base, p.g, node)

	err := restc.Post(urlstr, nil, obj)

	return err
}

func (p Proxy) GetNode(node string, obj interface{}) error {

	urlstr := restc.Url(p.base, p.g, node)

	err := restc.Put(urlstr, nil, obj)

	return err
}

func (p Proxy) Edges(src, rel string) (edges []graph.Edge, err error) {

	urlstr := restc.Url(p.base, p.g, src, rel)
	
	err = restc.Get(urlstr, nil, &edges)

	return
}

func (p Proxy) EdgesSince(src, rel string, since int) (edges []graph.Edge, err error) {

	params := params{since: strconv.Itoa(since), block:"true"}

	urlstr := restc.Url(p.base, p.g, src, rel)
	
	err = restc.Get(urlstr, params, &edges)

	return
}

func (p Proxy) EdgesExactly(src, rel string, since int, n int) (edges []graph.Edge, err error) {

	params := params{since: strconv.Itoa(since), block:"true", min:strconv.Itoa(n), max:strconv.Itoa(n)}

	urlstr := restc.Url(p.base, p.g, src, rel)
	
	err = restc.Get(urlstr, params, &edges)

	return
}

func (p Proxy) EdgesLimited(src, rel string, since int, min, max int) (edges []graph.Edge, err error) {

	params := params{since: strconv.Itoa(since), block:"true", min:strconv.Itoa(min), max:strconv.Itoa(max)}

	urlstr := restc.Url(p.base, p.g, src, rel)
	
	err = restc.Get(urlstr, params, &edges)

	return
}

func (p Proxy) Watch(src, rel string, since int, handler EdgeHandler) {

	for {

		edges, err := p.EdgesSince(src, rel, since)

		// ignore errors for now
		if err != nil {
			return			
		}

		for _, edge := range edges {

			if edge.Index <= since {
				return
			}

			since = edge.Index

			handler(edge)
		}
	}
}
